<?php
/**
 * Modelo CRUD de destinatários
 * @author Emanuel Melo e Renato Lenz @ PC4 Team
 */
class PC4_Crud_Newsletter_Destinatario extends PC4_Crud_Abstrato_Rastreado {
	
	public $campo_contato;
	
	/**
	 * Construtor
	 */
	function __construct($tabela = 'destinatarios', $campo_contato = 'contato') {
		parent::__construct($tabela);
		$this->campo_contato = $campo_contato;
	}
	
	/**
	 * Devolve o contato do destinatário
	 * @return the $campo_contato
	 */
	public function getContato($r) {
		return $r->contato;
	}

	/**
	 * Faz a validação dos campos
	 * @param array $campos
	 * @param int $id
	 * @return array com mensagens de erros
	 */
	function valida($campos, $id = 0) {
		$erros = array();
		
		if (empty($campos["id_clientes"])) {
			$erros[] = "N&atilde;o foi poss&iacute;vel recuperar as informa&ccedil;&otilde;es da sua sess&atilde;o.";
		}
		if (empty($campos['contato'])) {
			$erros[] = "Informe um " . $this->campo_contato;
		}
		else {
			$q = $this->consulta("contato = '{$campos['contato']}' AND id_clientes = " . $campos["id_clientes"] . " AND id <> $id", 1, 1);
		
			if (!empty($q)) {
				$r = $this->trataRegistro((object)$campos);
				$erros[] = "O " . $this->campo_contato . " '" . $this->getContato($r) . "' já existe em nossa base de dados.";
			}
		}
		
		return $erros;
	}
	
	/**
	 * Recebe um array com os campos e insere na base de dados o novo registro
	 * @param array $umRegistro
	 * @return O id inserido ou um array com mensagens de erro
	 */
	function insere($umRegistro) {
		$mdescritor = new PC4_Crud_Newsletter_DescritorDestinatario();
		
		$descritores = $umRegistro['descritores'];
		unset($umRegistro['descritores']);
		$idDestinatario = parent::insere($umRegistro);

		if (is_numeric($idDestinatario)) {
			foreach ((array)$descritores as $idPalavraChave => $valor) {
				$descritor = array(
					'id_destinatarios' => $idDestinatario,
					'id_palavras_chaves' => $idPalavraChave,
					'valor' => $valor
				);
				$erro_descritor = $mdescritor->insere($descritor);
				if (!is_numeric($erro_descritor)) {
					$erros = array_merge($erros, $erro_descritor);
				}
			}
		}
		
		return $idDestinatario;
	}
	
	/**
	 * 
	 * @param array $umRegistro
	 * @param int $id
	 * @return devolve um array de erros (nomeCampo/erro) para cada campo que não passou da validação 
	 */
	function edita($umRegistro, $id) {
		$mdescritor = new PC4_Crud_Newsletter_DescritorDestinatario();
		
		$descritores = $umRegistro['descritores'];
		unset($umRegistro['descritores']);
		$erros = parent::edita($umRegistro, $id);
		
		if (empty($erros)) {
			$this->db->delete('descritores', 'id_destinatarios = ' . $id);
			
			foreach ((array)$descritores as $idPalavraChave => $valor) {
				$descritor = array(
					'id_destinatarios' => $id,
					'id_palavras_chaves' => $idPalavraChave,
					'valor' => $valor
				);
				$erro_descritor = $mdescritor->insere($descritor);
				if (!is_numeric($erro_descritor)) {
					$erros = array_merge($erros, $erro_descritor);
				}
			}
			
		}
		return $erros;
	}
	
	/**
	 * Gera uma lista de registro com paginação - padrão 20 registros por página
	 */
	function listaExibiveis($id_cliente, $pagina = 1, $registros = 30, $exibir = 1) {
		$this->db->select("(
				    SELECT
				      CONCAT(
				        '{',
				        GROUP_CONCAT(CONCAT('\"', pc2.nome, '\":\"', IFNULL(d4.valor, ''), '\"')),
				        '}'
				      )
				    FROM
				      destinatarios d3
				      LEFT JOIN clientes_rel_palavras_chaves crpc2
				        ON   crpc2.id_clientes = d3.id_clientes
				      LEFT JOIN palavras_chave pc2
				        ON   pc2.id = crpc2.id_palavras_chaves
				        AND crpc2.exibir IN ($exibir)
				      LEFT JOIN descritores d4
				        ON   d4.id_palavras_chaves = pc2.id
				        AND d4.id_destinatarios = d3.id
				    WHERE
				      d3.id = d.id
				    GROUP BY
				      d3.id
				    LIMIT 1
				  ) AS descritores,
				  d.*", false);
		$this->db->join('clientes_rel_palavras_chaves crpc', 'd.id_clientes = crpc.id_clientes', 'left');
		$this->db->join('palavras_chave pc', 'pc.id = crpc.id_palavras_chaves AND crpc.exibir IN (' . $exibir . ')', 'left');
		$this->db->join('descritores d2', 'd2.id_palavras_chaves = pc.id AND d2.id_destinatarios = d.id', 'left');
		$this->db->group_by('d.id');
		$this->db->where('d.id_clientes = ' . $id_cliente);
		return $this->lista($pagina, $registros);
	}

	/**
	 * Gera uma lista de registros com paginação feita por uma busca - padrão 20 registros por página
	 * @param int $id_cliente
	 * @param string $string
	 * @param int $pagina
	 * @param int $registros
	 * 
	 * @return array de registros da busca
	 */
	function listaBusca($id_cliente, $string, $pagina = 1, $registros = 30) {
		$string = $this->db->escape_str($string);
		$this->db->where("(d2.valor LIKE '%$string%' OR d.contato LIKE '%$string%')");
		$rs = $this->listaExibiveis($id_cliente, $pagina, $registros);

		return $rs;
	}
	
	/**
	 * Executa uma consulta retornando as informações sobre os destinatários do cliente
	 * @param int $id_cliente
	 * @param int $pagina
	 * @param int $registros
	 * @return array com destinatários do cliente
	 */
	function listaDoCliente($id_cliente, $pagina = 1, $registros = 20, $exibir = 1) {
		$rs = $this->listaExibiveis($id_cliente, $pagina, $registros, $exibir);
		
		$destinatarios_cliente = array();
		foreach ($rs as $r) {
			$descritores = implode(' - ', $r->descritores);
			$destinatarios_cliente[$r->id] = $this->getContato($r) . ' - ' . $descritores;
		}

		return $destinatarios_cliente;
	}
	
	/**
	 * Executa uma consulta retornando as informações sobre os destinatários da lista
	 * @param int $id_lista
	 * @param int $pagina
	 * @param int $registros
	 * @return array com destinatários da lista
	 */
	function listaDaLista($id_lista, $pagina = 1, $registros = -1) {
		if ($registros != -1) {
			$offset = ($pagina - 1) * $registros;
			$limite = "LIMIT $offset, $registros";
		}
		$rs = $this->db->query("
				SELECT
				  CONCAT(
				    '{',
				    GROUP_CONCAT(CONCAT('\"', pc.nome, '\":\"', IFNULL(d2.valor, ''), '\"')),
				    '}'
				  ) AS descritores,
				  d.*
				FROM
				  destinatarios d
				  INNER JOIN listas_rel_destinatarios lrd
				    ON   lrd.id_destinatarios = d.id
				  LEFT JOIN clientes_rel_palavras_chaves crpc
				    ON   d.id_clientes = crpc.id_clientes
				  LEFT JOIN palavras_chave pc
				    ON   pc.id = crpc.id_palavras_chaves
				    AND crpc.exibir = 1
				  LEFT  JOIN descritores d2
				    ON   d2.id_palavras_chaves = pc.id
				    AND d2.id_destinatarios = d.id
				WHERE
				  lrd.id_listas = $id_lista
				GROUP BY
				  d.id
				$limite  
			")->result();
		
		$destinatarios_lista = array();
		foreach ($rs as $c => $r) {
			$d = $this->trataRegistro($r);
			$descritores = implode(' - ', $r->descritores);
			$destinatarios_lista[$d->id] = $this->getContato($r) . ' - ' . $descritores;
		}
		return $destinatarios_lista;
	}
	
	/**
	 * Executa uma consulta retornando as informações sobre os destinatários do cliente
	 * @param int $id_cliente
	 * @return array com destinatários organizados por lista
	 */
	function listaOrganizada($id_cliente, $exibir = 1) {
		
		$rs = $this->db->query("
				SELECT
				  CONCAT(
				    '{',
				    GROUP_CONCAT(CONCAT('\"', pc.nome, '\":\"', IFNULL(d2.valor, ''), '\"')),
				    '}'
				  ) AS descritores,
				  d.id AS 'id_destinatario',
				  d.contato,
				  IFNULL(l.nome, 'Outros') AS 'nome_lista'
				FROM
				  destinatarios d
				  LEFT JOIN listas_rel_destinatarios lrd
				    ON   lrd.id_destinatarios = d.id
				  LEFT JOIN listas l
				    ON   l.id = lrd.id_listas
				  LEFT JOIN clientes_rel_palavras_chaves crpc
				    ON   d.id_clientes = crpc.id_clientes
				  LEFT JOIN palavras_chave pc
				    ON   pc.id = crpc.id_palavras_chaves
				    AND crpc.exibir IN ($exibir)
				  LEFT  JOIN descritores d2
				    ON   d2.id_palavras_chaves = pc.id
				    AND d2.id_destinatarios = d.id
				WHERE
				  d.id_clientes = $id_cliente
				GROUP BY
				  d.id, l.id
				ORDER BY l.id DESC
			")->result();
		
		$listas = array();
		foreach ($rs as $c => $r) {
			$r = $this->trataRegistro($r);
			$listas[$r->nome_lista][$r->id_destinatario] = $r;
		}
		return $listas;
	}	
	
	/**
	 * Recupera um registro pelo id
	 * @param $id
	 * @return object de registro
	 */
	function ve($id) {
		$r = parent::ve($id);
		$r->descritores = $this->getPalavrasChave($r->id_clientes, $id);
		return $r;
	}
	
	/**
	 * Apaga um registro
	 * @param int $id
	 */
	function apaga($id) {
		$this->db->delete("listas_rel_destinatarios", "id_destinatarios = $id");
		$this->db->delete('descritores', 'id_destinatarios = ' . $id);
		return parent::apaga($id);
	}
	
	/**
	 * Apaga todos os destinatarios de um cliente
	 * @param int $id_cliente
	 * @return int Linhas afetadas
	 */
	function apagaPorCliente($id_cliente) {
		$this->db->delete("listas_rel_destinatarios", "id_destinatarios IN (SELECT id FROM destinatarios WHERE id_clientes = $id_cliente)");
		$this->db->delete("descritores", "id_destinatarios IN (SELECT id FROM destinatarios WHERE id_clientes = $id_cliente)");
		$this->db->delete($this->tabela, "id_clientes = '$id_cliente'");
		
		return $this->db->affected_rows();
	}
	
	/**
	 * Recupera os descritores das palavras chaves selecionadas pelo cliente
	 * @param int $id_cliente
	 * @param int $id_destinatario
	 */
	function getPalavrasChave($id_cliente, $id_destinatario = -1) {
		$rs = $this->db->query(
				" SELECT
				    pc.id AS 'id_palavra_chave',
				    pc.nome AS 'palavra_chave',
				    tb_valor.valor
				  FROM
				    clientes_rel_palavras_chaves crpc
				    INNER JOIN palavras_chave pc
				      ON   pc.id = crpc.id_palavras_chaves
				    LEFT JOIN (
				           SELECT
				             pc2.id,
				             d.valor
				           FROM
				             descritores d
				             INNER JOIN palavras_chave pc2
				               ON   pc2.id = d.id_palavras_chaves
				           WHERE
				             d.id_destinatarios = '$id_destinatario'
				         ) tb_valor
				      ON   tb_valor.id = pc.id
				  WHERE
				    crpc.id_clientes = $id_cliente"
		)->result();
		
		return $rs;
	}

		
	/**
	 * Altera o modo como os registros aparecerão para o usuário
	 * @param object $registro
	 * @return object de registros alterados
	 */
	function trataRegistro($registro) {
		$registro->descritores = (array)json_decode($registro->descritores);
		
		return $registro;
	}
	
	/**
	 * Retorna dados necessários para montar documento excel com
	 * os destinatários e os respectivos descritores e valores de
	 * suas palavras-chave
	 * @param int $id
	 */
	function exportaExcel($id, $modelo) {
		$excel_model = new PC4_Util_Excel();
		
		$rs = $this->listaExibiveis($id, 1, -1, "0,1");

		if (!empty($rs)) {
			$r = current($rs);
			$cabecalhos = array_keys($r->descritores);
			array_unshift($cabecalhos, $this->campo_contato);
		}

		if ($modelo) {
			return $excel_model->exporta(array(), $cabecalhos, "csv");
		}

		$tabelas = "";
		$registros = array();
		foreach ($rs as $c => $r) {
			$registro = $r->descritores;
			array_unshift($registro, $this->getContato($r));
			$registros[] = $registro;
		}
		$tabelas .= $excel_model->exporta($registros, $cabecalhos);
		
		return $tabelas;
		
	}
	
	/**
	 * Importa o arquivo excel cadastrando os destinatários
	 * @return 
	 */
	function importaExcel($arquivo, $id_cliente) {
		$palavras_chave_model = new PC4_Crud_Newsletter_PalavraChave();
		$descritores_model = new PC4_Crud_Newsletter_DescritorDestinatario();
		$excel_model = new PC4_Util_Excel();
		
		$r = $excel_model->importaCSV($arquivo);
		$rs = $r['rs'];
		$cabecalhos = $r['cabecalhos'];
		unset($cabecalhos[0]);
		
		// Valida cabeçalhos
		$rs_palavras = $palavras_chave_model->getPalavrasChaveCliente($id_cliente);
		$id_cabecalhos = array();
		foreach ($cabecalhos as $coluna => $cabecalho) {
			$ok = false;
			foreach ($rs_palavras as $palavra) {
				if ($palavra->nome == $cabecalho) {
					$id_cabecalhos[$coluna] = $palavra->id;
					$ok = true;
					break;
				}
				
			}
			if (!$ok) {
				$erros[] = "O Cabe&ccedil;alho \"$cabecalho\" n&atilde;o existe.";
			}
		}

		if (!empty($erros)) {
			return "Arquivo inv&aacute;lido. Por favor, certifique-se de que seu arquivo esteja igual ao modelo de importa&ccedil;&atilde;o.<br />Erros: " . implode("<br />", $erros);
		}
		
		$destinatarios = array();
		$descritores = array();
		
		foreach ($rs as $linha => $r) {
			$destinatarios[$linha] = array(
				'id_clientes' => $id_cliente,
				'contato' => $r[0]
			);
			
			$descritores[$linha] = array();
			for ($coluna = 1; $coluna < count($r); $coluna++) {
				if (!empty($r[$coluna])) {
					$descritores[$linha][] = array(
						'id_palavras_chaves' => $id_cabecalhos[$coluna],
						'valor' => $r[$coluna]
					);
				}
			}
		}

		$this->db->trans_begin();
		$ids = $this->insereVarios($destinatarios);
		
		if (!is_numeric(current($ids))) {
			return $ids;
		}

		$inserir_descritores = array();
		foreach ($ids as $linha => $id) {
			foreach ($descritores[$linha] as $descritor) {
				$descritor['id_destinatarios'] = $id;
				$inserir_descritores[] = $descritor;
			}
		}
		$erros = $descritores_model->insereVarios($inserir_descritores, 'id_destinatarios');
//d($erros);
		if (!is_numeric(current($erros))) {
		    $this->db->trans_rollback();
		    return $erros;
		}
		else {
		    $this->db->trans_commit();
		}

		return count($ids);
	}
	
}

?>